package com.nd.fastdp.workflow.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nd.fastdp.framework.exception.BusinessException;
import com.nd.fastdp.framework.pojo.dto.DelParam;
import com.nd.fastdp.framework.pojo.dto.StateParam;
import com.nd.fastdp.org.model.bo.org.DeptBO;
import com.nd.fastdp.org.model.bo.user.UserBO;
import com.nd.fastdp.org.model.dto.user.UserListParam;
import com.nd.fastdp.org.service.DeptService;
import com.nd.fastdp.org.service.UserService;
import com.nd.fastdp.workflow.constant.AssigneeType;
import com.nd.fastdp.workflow.constant.OptionalRangeType;
import com.nd.fastdp.workflow.convert.ProcdefConvert;
import com.nd.fastdp.workflow.dao.ProcdefMapper;
import com.nd.fastdp.workflow.model.bo.procdef.ProcdefBO;
import com.nd.fastdp.workflow.model.dto.procdef.*;
import com.nd.fastdp.workflow.model.entity.Procdef;
import com.nd.fastdp.workflow.model.pojo.Node;
import com.nd.fastdp.workflow.serivce.ProcdefService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service
public class ProcdefServiceImpl implements ProcdefService {

    @Autowired
    private ProcdefMapper procdefMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private DeptService deptService;


    @Override
    public ProcdefBO add(ProcdefAddParam param) {

        Procdef procdef = ProcdefConvert.INSTANCE.from(param);

        procdefMapper.insert(procdef);

        return ProcdefConvert.INSTANCE.to(procdef);
    }

    @Override
    public void del(DelParam param) {
        procdefMapper.del(param);
    }

    @Override
    public ProcdefBO modify(ProcdefModifyParam param) {

        Procdef procdef = ProcdefConvert.INSTANCE.from(param);

        procdefMapper.updateById(procdef);

        return get(procdef.getId());
    }

    @Override
    public void modifyState(StateParam param) {
        procdefMapper.updateState(param);
    }

    @Override
    public ProcdefBO get(String id) {

        Procdef procdef = procdefMapper.selectById(id);

        return ProcdefConvert.INSTANCE.to(procdef);
    }

    @Override
    public ProcdefBO getByCode(String code) {

        Procdef procdef = procdefMapper.getByCode(code);

        return ProcdefConvert.INSTANCE.to(procdef);
    }

    @Override
    public List<ProcdefBO> listAllEnable() {

        List<Procdef> procdefs =  procdefMapper.listAllEnable();

        return ProcdefConvert.INSTANCE.to(procdefs);
    }

    @Override
    public List<ProcdefBO> listAll() {

        List<Procdef> procdefs =  procdefMapper.listAll();

        return ProcdefConvert.INSTANCE.to(procdefs);
    }

    @Override
    public List<ProcdefBO> list(ProcdefListParam param) {

        List<Procdef> procdefs =  procdefMapper.list(param);

        return ProcdefConvert.INSTANCE.to(procdefs);
    }

    @Override
    public Page<ProcdefBO> page(ProcdefQueryParam param) {

        IPage<Procdef> page =  procdefMapper.page(param.getPage(), param);

        return ProcdefConvert.INSTANCE.to(page);
    }

    @Override
    public List<Node> flowLine(ProcdefFlowLineParam param) {

        if(StringUtils.isEmpty(param.getProcdefId())){
            throw new BusinessException("流程定义不存在");
        }

        Procdef procdef = procdefMapper.selectById(param.getProcdefId());

        if(procdef == null){
            throw new BusinessException("流程定义不存在");
        }

        JSONObject processData = JSON.parseObject(procdef.getConfig()).getJSONObject("processData");

        Node node = JSONObject.toJavaObject(processData, Node.class);

        List<Node> flowLine = node.flowline(param.getVar(), param.getLoginUser());

        for(Node n : flowLine){

            n.setChildNode(null);
            n.setConditionNodes(null);

            if(AssigneeType.DIRECTOR.getValue().equals(n.getProperties().getAssigneeType())){

                UserBO userBO = userService.get(param.getLoginUser().getUserId());

                DeptBO deptBO = deptService.get(userBO.getDept());
                DeptBO deptBOLevel2 = null;
                DeptBO deptBOLevel3 = null;
                DeptBO deptBOLevel4 = null;
                DeptBO deptBOLevel5 = null;
                DeptBO deptBOLevel6 = null;

                if(StringUtils.isNotEmpty(deptBO.getParentId())){
                    deptBOLevel2 = deptService.get(deptBO.getParentId());
                }

                if(deptBOLevel2 != null && StringUtils.isNotEmpty(deptBOLevel2.getParentId())){
                    deptBOLevel3 = deptService.get(deptBOLevel2.getParentId());
                }

                if(deptBOLevel3 != null && StringUtils.isNotEmpty(deptBOLevel3.getParentId())){
                    deptBOLevel4 = deptService.get(deptBOLevel3.getParentId());
                }

                if(deptBOLevel4 != null && StringUtils.isNotEmpty(deptBOLevel4.getParentId())){
                    deptBOLevel5 = deptService.get(deptBOLevel4.getParentId());
                }

                if(deptBOLevel5 != null && StringUtils.isNotEmpty(deptBOLevel5.getParentId())){
                    deptBOLevel6 = deptService.get(deptBOLevel5.getParentId());
                }

                Integer leaderLevel = 1;

                String leaderLevelStr = n.getContent().replaceAll("直接主管", "").replaceAll("第", "").replaceAll("级主管", "");
                if(StringUtils.isNotEmpty(leaderLevelStr)){
                    leaderLevel = Integer.parseInt(leaderLevelStr);
                }

                DeptBO actionerDept = null;
                switch (leaderLevel){

                    case 1:
                        actionerDept = deptBO;

                        if((actionerDept == null || StringUtils.isEmpty(actionerDept.getLeader()))){
                            actionerDept = deptBOLevel2;
                        }

                        break;

                    case 2:
                        actionerDept = deptBOLevel2;

                        if((actionerDept == null || StringUtils.isEmpty(actionerDept.getLeader()))){
                            actionerDept = deptBOLevel3;
                        }

                        break;

                    case 3:
                        actionerDept = deptBOLevel3;

                        if((actionerDept == null || StringUtils.isEmpty(actionerDept.getLeader()))){
                            actionerDept = deptBOLevel4;
                        }

                        break;

                    case 4:
                        actionerDept = deptBOLevel4;

                        if((actionerDept == null || StringUtils.isEmpty(actionerDept.getLeader()))){
                            actionerDept = deptBOLevel5;
                        }

                        break;

                    case 5:
                        actionerDept = deptBOLevel5;

                        if((actionerDept == null || StringUtils.isEmpty(actionerDept.getLeader()))){
                            actionerDept = deptBOLevel6;
                        }
                        break;

                    default:
                }

                if(actionerDept != null && StringUtils.isNotEmpty(actionerDept.getLeader())){

                    UserBO leader = userService.get(actionerDept.getLeader());

                    List<Map<String, Object>> menbers = Arrays.asList(JSON.parseObject(JSONObject.toJSONString(leader), Map.class));

                    n.getProperties().setMenbers(menbers);
                }

            }else if(AssigneeType.MYSELF.getValue().equals(n.getProperties().getAssigneeType())){

                UserBO myself = userService.get(param.getLoginUser().getUserId());
                List<Map<String, Object>> menbers = Arrays.asList(JSON.parseObject(JSONObject.toJSONString(myself), Map.class));

                n.getProperties().setMenbers(menbers);

            }else if(AssigneeType.POSITION.getValue().equals(n.getProperties().getAssigneeType())){

                List<Map<String, Object>> positions = n.getProperties().getMenbers();
                n.getProperties().setPositions(positions);

                n.getProperties().setMenbers(new ArrayList<>());

                for(Map<String, Object> position : positions){

                    UserListParam userListParam = new UserListParam();
                    userListParam.setLoginUser(param.getLoginUser());
                    userListParam.setPosition((String)position.get("id"));

                    List<UserBO> users = userService.list(userListParam);

                    for (UserBO userBO : users){
                        n.getProperties().getMenbers().add(JSON.parseObject(JSONObject.toJSONString(userBO), Map.class));
                    }
                }

            }else if(AssigneeType.ROLE.getValue().equals(n.getProperties().getAssigneeType())){

                List<Map<String, Object>> roles = n.getProperties().getMenbers();
                n.getProperties().setRoles(roles);

                n.getProperties().setMenbers(new ArrayList<>());

                for(Map<String, Object> role : roles){

                    List<UserBO> users = userService.listByRoleId((String)role.get("id"));

                    for (UserBO userBO : users){
                        n.getProperties().getMenbers().add(JSON.parseObject(JSONObject.toJSONString(userBO), Map.class));
                    }
                }

            /**
             * 发起人自选
              */
            }else if(AssigneeType.OPTIONAL.getValue().equals(n.getProperties().getAssigneeType())){

                n.getProperties().setUserOptional(true);

                if(OptionalRangeType.POSITION.getValue().equals(n.getProperties().getOptionalRange())){

                    List<Map<String, Object>> positions = n.getProperties().getMenbers();
                    n.getProperties().setPositions(positions);

                    n.getProperties().setMenbers(new ArrayList<>());
                    n.getProperties().setUsers(new ArrayList<>());

                    for(Map<String, Object> position : positions){

                        UserListParam userListParam = new UserListParam();
                        userListParam.setLoginUser(param.getLoginUser());
                        userListParam.setPosition((String)position.get("id"));

                        List<UserBO> users = userService.list(userListParam);

                        for (UserBO userBO : users){
                            n.getProperties().getUsers().add(JSON.parseObject(JSONObject.toJSONString(userBO), Map.class));
                        }
                    }

                    if(n.getProperties().getOptionalMultiUser()){
                        n.getProperties().setMenbers(n.getProperties().getUsers());
                    }else{
                        if(n.getProperties().getUsers().size() > 0){
                            n.getProperties().getMenbers().add((Map<String, Object>)n.getProperties().getUsers().get(0));
                        }
                    }

                }else if(OptionalRangeType.ROLE.getValue().equals(n.getProperties().getOptionalRange())){

                    List<Map<String, Object>> roles = n.getProperties().getMenbers();
                    n.getProperties().setRoles(roles);

                    n.getProperties().setUsers(new ArrayList<>());
                    n.getProperties().setMenbers(new ArrayList<>());

                    for(Map<String, Object> role : roles){

                        List<UserBO> users = userService.listByRoleId((String)role.get("id"));

                        for (UserBO userBO : users){
                            n.getProperties().getUsers().add(JSON.parseObject(JSONObject.toJSONString(userBO), Map.class));
                        }
                    }

                    if(n.getProperties().getOptionalMultiUser()){
                        n.getProperties().setMenbers(n.getProperties().getUsers());
                    }else{
                        if(n.getProperties().getUsers().size() > 0){
                            n.getProperties().getMenbers().add((Map<String, Object>)n.getProperties().getUsers().get(0));
                        }
                    }

                }else if(OptionalRangeType.USER.getValue().equals(n.getProperties().getOptionalRange())){

                    n.getProperties().setUsers(n.getProperties().getMenbers());
                }
            }
        }

        return flowLine;
    }
}
